#include "webglk/glk.h"
#include <stdint.h>
#include "main.h"
#include "glulx.h"
#include <stdio.h>

static void savePointer(int32_t offs,uint32_t struc,uint32_t val)
{
	if (offs==-1) push(val);
	else if (offs) write32(offs+struc,val);
}

uint32_t handleGlk(uint32_t f,uint32_t *args,uint8_t numArgs)
{
	uint32_t r;
	switch(f)
	{
		case 0x04:
			return glk_gestalt(args[0],args[1]);
		case 0x20:
		{
			glui32 rock;
			r=glk_window_iterate(args[0],&rock);
			savePointer(args[1],0,rock);
			return r;
		}
		case 0x21:
			return glk_window_get_rock(args[0]);
		case 0x22:
			return glk_window_get_root();
		case 0x23:
			return glk_window_open(args[0],args[1],args[2],args[3],args[4]);
		case 0x24:
		{
			stream_result_t result;
			glk_window_close(args[0],&result);
			savePointer(args[1],0,result.readcount);
			savePointer(args[1],4,result.writecount);
			return 0;
		}
		case 0x25:
		{
			glui32 width,height;
			glk_window_get_size(args[0],&width,&height);
			savePointer(args[1],0,width);
			savePointer(args[2],0,height);
			return 0;
		}
		case 0x26:
			glk_window_set_arrangement(args[0],args[1],args[2],args[3]);
			return 0;
		case 0x29:
			return glk_window_get_parent(args[0]);
		case 0x2a:
			glk_window_clear(args[0]);
			return 0;
		case 0x2b:
			glk_window_move_cursor(args[0],args[1],args[2]);
			return 0;
		case 0x2f:
			glk_set_window(args[0]);
			return 0;
		case 0x40:
		{
			glui32 rock;
			r=(uint32_t)glk_stream_iterate((strid_t)args[0],&rock);
			savePointer(args[1],0,rock);
			return r;
		}
		case 0x42:
			return glk_stream_open_file(args[0],args[1],args[2]);
		case 0x43:
			return glk_stream_open_memory((char *)(rom+args[0]),args[1],args[2],args[3]);
		case 0x44:
		{
			stream_result_t result;
			glk_stream_close(args[0],&result);
			savePointer(args[1],0,result.readcount);
			savePointer(args[1],4,result.writecount);
			return 0;
		}
		case 0x45:
			glk_stream_set_position(args[0],args[1],args[2]);
			return 0;
		case 0x47:
			glk_stream_set_current(args[0]);
			return 0;
		case 0x48:
			return glk_stream_get_current();
		case 0x61:
		{
			if (rom[args[1]]!=0xe0)
				fatal("Called fileref_create with a compressed string");
			return glk_fileref_create_by_name(args[0],(char *)(rom+args[1]+1),args[2]);
		}
		case 0x62:
			return glk_fileref_create_by_prompt(args[0],args[1],args[2]);
		case 0x63:
			glk_fileref_destroy(args[0]);
			return 0;
		case 0x64:
		{
			glui32 rock;
			r=glk_fileref_iterate(args[0],&rock);
			savePointer(args[1],0,rock);
			return r;
		}
		case 0x67:
			return glk_fileref_does_file_exist(args[0]);
		case 0x81:
			glk_put_char_stream(args[0],args[1]);
			return 0;
		case 0x86:
			glk_set_style(args[0]);
			return 0;
		case 0xa0:
			return glk_char_to_lower(args[0]);
		case 0xa1:
			return glk_char_to_upper(args[0]);
		case 0xb0:
			glk_stylehint_set(args[0],args[1],args[2],args[3]);
			return 0;
		case 0xb1:
			glk_stylehint_clear(args[0],args[1],args[2]);
			return 0;
		case 0xc0:
			g.event=args[0];
			done++;
			return 0;
		case 0xd0:
			g.inputbuffer=args[1];
			glk_request_line_event(args[0],(char *)(rom+args[1]),args[2],args[3]);
			return 0;
		case 0xd2:
			glk_request_char_event(args[0]);
			return 0;
		case 0xd3: //blargh
			glk_cancel_char_event(args[0]);
			return 0;
		case 0xd4:
			glk_request_mouse_event(args[0]);
			return 0;
		case 0xd5: //argh!
			glk_cancel_mouse_event(args[0]);
			return 0;
		case 0xd6:
			glk_request_timer_events(args[0]);
			return 0;
		case 0xe0:
		{
			glui32 width,height;
			r=glk_image_get_info(args[0],&width,&height);
			savePointer(args[1],0,width);
			savePointer(args[2],0,height);
			return r;
		}
		case 0xe1:
			return glk_image_draw(args[0],args[1],args[2],args[3]);
		case 0xe2:
			return glk_image_draw_scaled(args[0],args[1],args[2],args[3],args[4],args[5]);
		case 0xea:
			glk_window_fill_rect(args[0],args[1],args[2],args[3],args[4],args[5]);
			return 0;
		case 0xeb:
			glk_window_set_background_color(args[0],args[1]);
			return 0;
		case 0xf0:
		{
			glui32 rock;
			r=glk_schannel_iterate(args[0],&rock);
			savePointer(args[1],0,rock);
			return r;
		}
		case 0x100:
			glk_set_hyperlink(args[0]);
			return 0;
		case 0x102:
			glk_request_hyperlink_event(args[0]);
			return 0;
		case 0x128:
			glk_put_char_uni(args[0]);
			return 0;
		case 0x139:
			return glk_stream_open_memory_uni((glui32*)rom+args[0],args[1],args[2],args[3]);
		default: fatal("Invalid glk function %x",f);
	}
	return 0;
}
